package com.pkk.penguin.frame.know.java.driven.beanleftcycle.bean;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.BeanPostProcessor;

/**
 * @description: 一个bean
 * @author: peikunkun
 * @create: 2020-08-04 11:17
 **/
@Slf4j
public class BeanLeftCycleBean3 implements BeanPostProcessor, InitializingBean, DisposableBean {

  public BeanLeftCycleBean3() {
    System.out.println(this.getClass().getSimpleName() + "【构造器】  Constructor ...");
  }

  /**
   * Apply this BeanPostProcessor to the given new bean instance <i>before</i> any bean initialization callbacks (like
   * InitializingBean's {@code afterPropertiesSet} or a custom init-method). The bean will already be populated with
   * property values. The returned bean instance may be a wrapper around the original.
   * <p>The default implementation returns the given {@code bean} as-is.
   *
   * @param bean the new bean instance
   * @param beanName the name of the bean
   * @return the bean instance to use, either the original or a wrapped one; if {@code null}, no subsequent
   * BeanPostProcessors will be invoked
   * @throws BeansException in case of errors
   * @see InitializingBean#afterPropertiesSet
   */
  @Override
  public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    System.out.println(this.getClass().getSimpleName() + " 【BeanPostProcessor#postProcessBeforeInitialization】 [" + beanName + "]");
    return bean;
  }

  /**
   * Apply this BeanPostProcessor to the given new bean instance <i>after</i> any bean initialization callbacks (like
   * InitializingBean's {@code afterPropertiesSet} or a custom init-method). The bean will already be populated with
   * property values. The returned bean instance may be a wrapper around the original.
   * <p>In case of a FactoryBean, this callback will be invoked for both the FactoryBean
   * instance and the objects created by the FactoryBean (as of Spring 2.0). The post-processor can decide whether to
   * apply to either the FactoryBean or created objects or both through corresponding {@code bean instanceof
   * FactoryBean} checks.
   * <p>This callback will also be invoked after a short-circuiting triggered by a
   * {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method, in contrast to all other
   * BeanPostProcessor callbacks.
   * <p>The default implementation returns the given {@code bean} as-is.
   *
   * @param bean the new bean instance
   * @param beanName the name of the bean
   * @return the bean instance to use, either the original or a wrapped one; if {@code null}, no subsequent
   * BeanPostProcessors will be invoked
   * @throws BeansException in case of errors
   * @see InitializingBean#afterPropertiesSet
   * @see FactoryBean
   */
  @Override
  public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    System.out.println(this.getClass().getSimpleName() + " 【BeanPostProcessor#postProcessAfterInitialization】 [" + beanName + "]");
    return bean;
  }

  /**
   * Invoked by a BeanFactory on destruction of a singleton.
   *
   * @throws Exception in case of shutdown errors. Exceptions will get logged but not rethrown to allow other beans to
   * release their resources too.
   */
  @Override
  public void destroy() throws Exception {
    System.out.println(this.getClass().getSimpleName() + " 【DisposableBean】 destroy ...");
  }

  /**
   * Invoked by a BeanFactory after it has set all bean properties supplied (and satisfied BeanFactoryAware and
   * ApplicationContextAware).
   * <p>This method allows the bean instance to perform initialization only
   * possible when all bean properties have been set and to throw an exception in the event of misconfiguration.
   *
   * @throws Exception in the event of misconfiguration (such as failure to set an essential property) or if
   * initialization fails.
   */
  @Override
  public void afterPropertiesSet() throws Exception {
    System.out.println(this.getClass().getSimpleName() + " 【InitializingBean】 afterPropertiesSet ...");
  }
}
